home *** CD-ROM | disk | FTP | other *** search
Text File | 1992-11-22 | 37.2 KB | 1,473 lines |
-
- A.I.B.B.
- Amiga Intuition Based Benchmarks
- A system performance evaluation utility for the Amiga
-
- Program Release Version 5.5
- Copyright 1991,1992 LaMonte Koop
-
- Benchmark code examples and notes
-
- The code used for AIBB's benchmarking suite is rather simple in nature,
- but in order to provide a better view of what exactly each test does, a more
- thorough explanation for each is given in this document. In addition, a
- 'pseudo-C' code representation of each test is also supplied. This
- representation is not the full function itself, but rather a view of it
- which highlights the actual test material. What is missing from these
- representations is mostly initialization and cleanup code, and in some places
- the full C syntax is not applied as used in AIBB itself. However, this should
- give a fairly good picture of what is being done by AIBB during test
- performance.
- It should be noted that the code used is by no means optimized in some
- areas. Where optimization was prudent, it was used, but in some places this
- defeats the purpose.
-
- ==============================================================================
-
- WritePixel
-
- The WritePixel test is a very simple display of a given system's graphics
- throughput. It mainly deals with the operating system calls SetAPen()
- ( set the primary pen color ), and WritePixel() ( set a pixel in the current
- pen color ). This is a basic test of the efficiency of the operating system
- functions, as well as the speed of the custom hardware on the Amiga in these
- simple matters. Systems where the operating system kernel resides in a fast
- memory medium, as well as those which have more efficiency access to CHIP RAM
- resources will have the advantage with this test. The code representation
- for this test is given below:
-
-
- WritePixel_Test()
- {
- struct Screen *WPScreen;
- struct RastPort *rp;
- UWORD x;
- UWORD y;
- ULONG nulltime;
-
- /*
- * Although not shown, the screen and rastport variables are first set
- * up, then the test procedes at the following point....
- */
-
- START_TEST_TIMER;
-
- SetAPen(rp,1);
- for(y = 0; y < 200; y++)
- {
- for(x = 0; x < 320; x++)
- {
- WritePixel(rp,x,y);
- }
- }
- SetAPen(rp,0);
- for(x = 0; x < 320; x++)
- {
- for(y = 0; y < 200; y++)
- {
- WritePixel(rp,x,y);
- }
- }
- SetAPen(rp,1);
- for(y = 0; y < 200; y++)
- {
- Move(rp,0,y);
- Draw(rp,319,y);
- }
- SetAPen(rp,0);
- for(y = 0; y < 200; y++)
- {
- Move(rp,0,y);
- Draw(rp,320,y);
- }
- SetAPen(rp,1);
- for(y = 0; y < 200; y++)
- {
- Move(rp,0,y);
- Draw(rp,319,y);
- }
- SetAPen(rp,0);
- for(y = 0; y < 200; y++)
- {
- Move(rp,0,y);
- Draw(rp,320,y);
- }
- SetAPen(rp,1);
- for(y = 0; y < 200; y++)
- {
- Move(rp,0,y);
- Draw(rp,319,y);
- }
- SetAPen(rp,0);
- for(y = 0; y < 200; y++)
- {
- Move(rp,0,y);
- Draw(rp,320,y);
- }
- SetAPen(rp,1);
- for(y = 0; y < 200; y++)
- {
- for(x = 0; x < 320; x++)
- {
- WritePixel(rp,x,y);
- }
- }
- SetAPen(rp,0);
- for(x = 0; x < 320; x++)
- {
- for(y = 0; y < 200; y++)
- {
- WritePixel(rp,x,y);
- }
- }
- STOP_TEST_TIMER;
-
- /* That concludes the actual test code portion of this function */
- .................................................................
- }
-
- ==============================================================================
-
- IMath
-
- IMath is a test of the primary integer/logical operational efficiency of
- a system. Various integer arithmetic and logical function are performed in
- succession, and the calculations timed within a loop. The loop variable
- itself is used within the calculations in order to provide a dynamic quality
- to the generated code, instead of static values being used at all times.
- This test performs its operations on longword ( 32-bit ) values exclusively.
-
-
- IMath_Test()
- {
- LONG i;
- LONG a = 2;
- LONG b = 45;
- LONG c = 22;
-
- START_TEST_TIMER;
-
- for(i=0; i < 100000 ; i++)
- {
- a = (a * b) + i;
- b = (a * b) + (2 * i);
- c += ((c * a) + b) + i;
- c -= (((i + 1) - (a * b)) & ((b / a) | (i % 10))) + i;
- c += ((b * c) - (b / a) - i) ^ i + c;
- c -= (b / a) * (i + b);
- c += (((b / a) * c) - i) ^ i + c;
- c -= (((i + 1) - (a * b)) & ((b / a) | (i % 5))) - (5 * i);
- c += (b / a) * i;
- c -= (((b / a) * c) - i) ^ i + c;
- c += (((i + 1)-(a * b)) & ((b / a) | (i % 7))) - i;
- c -= (b / a) * (i - b);
- b = (a * b) - (b ^ a) - i;
- a = (a * b) + i;
- c += ((b / a) - i) ^ i;
- }
-
- STOP_TEST_TIMER;
-
- /*
- * At this point a global 'dummy' variable is used to assure that
- * code above is not optimized out. This makes a global optimizer
- * believe the above results are needed in order to assign the
- * dummy variable a value
- */
-
- TestDummy = a+b+c;
-
- /* The actual test code has concluded at this point */
- .................................................................
- }
-
- ==============================================================================
-
- Matrix
-
- This is AIBB's integer longword matrix manipulation test. Three matrices
- are used in a variety of operations, with stress being placed upon matrix
- manipulation ( data movement ) functions, as these are often primary functions
- performed on matrices. As the data here can not be kept entirely in registers
- for arithmetic manipulation, this test gives an indication of system
- performance when many data accesses are required outside of register values.
- The functions are also set up as to stress the calculation of data locations
- in the test timing. Note that systems with larger caches ( such as the
- MC68040 ) will have a general advantage here, although the matrices are quite
- large enough as to not permit them to be entirely cached. The outline function
- for the matrix test and its associated functions is given below:
-
-
- void Matrix_Test()
- {
- LONG *MatrixA;
- LONG *MatrixB;
- LONG *MatrixC;
- UWORD i;
- UWORD j;
- UWORD k;
-
- /*
- * Not shown, but the above LONG pointers are first initialized by
- * allocating 10000 bytes of memory for each and assigning them
- * to point at the base of each 'array'.
- */
-
- /*
- * The A and B arrays are first filled with values for later use
- */
-
- for(i=0; i<50; i++)
- {
- for(j=0; j<50; j++)
- {
- MatrixA[50*i+j] = (LONG)i+(LONG)j;
- MatrixB[50*i+j] = (LONG)(i+j) * (LONG)(j-i);
- }
- }
-
- START_TEST_TIMER;
-
- /*
- * Here is the actual test code. More emphasis is placed upon
- * matrix data movement than arithmetic operation as many matrix-
- * manipulation applications involve movement more than arithmetic
- * (though, execeptions seem to be the rule here :) ).
- * Though a purpose doesn't seem to be in mind here, it can give a
- * general manipulation 'feel' for the system.
- */
-
- for(k=0; k < 50; k++)
- {
- matrix_mult(MatrixA,MatrixB,MatrixC,50,50);
- for(i=0; i<50; i++)
- {
- matrix_row_swap(MatrixC,i,49-i,50);
- matrix_col_swap(MatrixC,49-i,i,50);
- }
- matrix_add(MatrixC,MatrixA,MatrixB,50,50);
- matrix_sub(MatrixB,MatrixA,MatrixC,50,50);
- matrix_transpose(MatrixC,MatrixA,50,50);
- }
-
- STOP_TEST_TIMER;
-
- /*
- * That concludes the test code proper. Clean up operations are
- * inserted following, and are not shown
- */
- ................................................................
- }
-
- /*
- * This function swaps rows in a matrix.
- */
-
- void matrix_row_swap(LONG *mat, UWORD ra, UWORD rb, UWORD ncols)
- {
- UWORD c;
- LONG t;
-
- for(c=0; c < ncols; c++)
- {
- t = mat[ra*ncols+c];
- mat[ra*ncols+c] = mat[rb*ncols+c];
- mat[rb*ncols+c] = t;
- }
- }
-
- /*
- * Same as above, but for column-swapping.
- */
-
- void matrix_col_swap(LONG *mat, UWORD ca, UWORD cb, UWORD nrows)
- {
- UWORD r;
- LONG t;
-
- for(r=0; r < nrows; r++)
- {
- t = mat[r*nrows+ca];
- mat[r*nrows+ca] = mat[r*nrows+cb];
- mat[r*nrows+cb] = t;
- }
- }
-
- /*
- * Add the contents of two matrices, and store the result in a third.
- * Equivalent to [C] = [A] + [B]
- */
-
- void matrix_add(LONG *matA, LONG *matB, LONG *matC, UWORD rows, UWORD cols)
- {
- UWORD r;
- UWORD c;
-
- for(r=0; r < rows; r++)
- {
- for(c=0; c < cols; c++)
- {
- matC[r*cols+c] = matA[r*cols+c] + matB[r*cols+c];
- }
- }
- }
-
- /*
- * Subtract the contents of two matrices, and store the result in a third.
- * Equivalent to [C] = [A] - [B].
- */
-
- void matrix_sub(LONG *matA, LONG *matB, LONG *matC, UWORD rows, UWORD cols)
- {
- UWORD r;
- UWORD c;
-
- for(r=0; r < rows; r++)
- {
- for(c=0; c<cols; c++)
- {
- matC[r*cols+c] = matA[r*cols+c] - matB[r*cols+c];
- }
- }
- }
-
- /*
- * Subtract the contents of two matrices, and store the result in a third.
- * Equivalent to [C] = [A] * [B].
- */
-
- void matrix_mult(LONG *matA, LONG *matB, LONG *matC, UWORD rows, UWORD cols)
- {
- UWORD r;
- UWORD c;
-
- for(r=0; r<rows; r++)
- {
- for(c=0; c<cols; c++)
- {
- matC[r*cols+c] = matA[r*cols+c] * matB[r*cols+c];
- }
- }
- }
-
- /*
- * Transpose the contents of matrix [B] to matrix [A]
- */
-
- void matrix_transpose(LONG *matA, LONG *matB, UWORD rows, UWORD cols)
- {
- UWORD r;
- UWORD c;
- LONG t;
-
- for(r=0; r < rows; r++)
- {
- for(c=0; c < cols; c++)
- {
- t = matA[r*cols+c];
- matA[r*cols+c] = matB[r*cols+c];
- matB[r*cols+c] = t;
- }
- }
- }
-
- ==============================================================================
-
- MemTest
-
- This function was primarily designed to test only the data movement
- efficiency of the system across FAST RAM buses.
-
- void MemTest()
- {
- UBYTE *FMemArray1;
- UBYTE *FMemArray2;
-
- /*
- * First (not shown), two arrays of 32K in size are allocated and
- * the reserved space split among the pointers above...
- */
-
- .................................................................
-
- /*
- * The actual test is a series of function calls, testing longword,
- * word, and byte transfer times.
- */
-
- START_TEST_TIMER;
-
- LongWordMemTest((ULONG *)FMemArray1,(ULONG *)FMemArray2,65);
- WordMemTest((UWORD *)FMemArray1,(UWORD *)FMemArray2,65);
- ByteMemTest((UBYTE *)FMemArray1,(UBYTE *)FMemArray2,65);
- LongWordMemTest((ULONG *)FMemArray1,(ULONG *)FMemArray2,65);
- WordMemTest((UWORD *)FMemArray1,(UWORD *)FMemArray2,65);
- ByteMemTest((UBYTE *)FMemArray1,(UBYTE *)FMemArray2,65);
-
- STOP_TEST_TIMER;
-
- /*
- * Clean up code would be placed in this location.
- */
- ...........................................................
- }
-
- /*
- * This function is responsible for LONGWORD memory access testing.
- */
-
- void LongWordMemTest(ULONG *MemArray1, ULONG *MemArray2, UWORD loops)
- {
- UWORD i;
- UWORD j;
-
- for(j=0; j < loops; j++)
- {
- for(i=0; i < 4096; i++)
- {
- *MemArray1++ = *MemArray2++;
- }
- for(i=0; i < 4096; i++)
- {
- *(--MemArray2) = *(--MemArray1);
- }
- }
- }
-
- /*
- * This function is responsible for WORD memory access testing.
- */
-
- void WordMemTest(UWORD *MemArray1, UWORD *MemArray2, UWORD loops)
- {
- register UWORD i;
- register UWORD j;
-
- for(j=0; j < loops; j++)
- {
- for(i=0; i < 8192; i++)
- {
- *MemArray1++ = *MemArray2++;
- }
- for(i=0; i < 8192; i++)
- {
- *(--MemArray2) = *(--MemArray1);
- }
- }
- }
-
- /*
- * This function is responsible for BYTE memory access testing.
- */
-
- void ByteMemTest(UBYTE *MemArray1, UBYTE *MemArray2, UWORD loops)
- {
- UWORD i;
- UWORD j;
-
- for(j=0; j < loops; j++)
- {
- for(i=0; i < 16384; i++)
- {
- *MemArray1++ = *MemArray2++;
- }
- for(i=0; i < 16384; i++)
- {
- *(--MemArray2) = *(--MemArray1);
- }
- }
- }
-
- ==============================================================================
-
- Sieve
-
- This test is the basic Sieve of Erosthenes, used often to benchmark system
- performance at a basic level. As the name implies, it is a 'sieve' for
- prime numbers, continuing up to the number 8191. The test is a counting
- test, primarily involved in array initialization, and value assignment.
-
-
- void Sieve()
- {
- UWORD k;
- UWORD iter;
- UWORD i;
- UWORD count;
- UWORD prime;
- BOOL flags[8191];
-
- START_TEST_TIMER;
-
- for(iter=0; iter < 200; iter++)
- {
- count = 0;
- for(i=0; i < 8191; i++) flags[i] = TRUE;
- for(i=0; i < 8191; i++)
- {
- if(flags[i])
- {
- prime = i + i + 3;
- for(k=i+prime; k < 8191; k += prime) flags[k] = FALSE;
- count++;
- }
- }
- }
-
- STOP_TEST_TIMER;
-
- /* End of test code */
-
- ..................................................................
- }
-
- ==============================================================================
-
- Sort
-
- A simple sorting test on a 60000 byte array ( arranged as 16-bit WORD
- values ). The algorithm used here is a shell-sort setup, with the array
- initialization itself also being part of the timed code. The sorting is
- timed for 5 passes, to allow better resolution in the results. ( lower
- numbers of passes tend to be too fast on accelerated systems ).
-
- void Sort()
- {
- WORD *sarray;
- WORD gap;
- WORD temp;
- WORD i;
- WORD j;
- BOOL nex;
-
- /*
- * In initializing for this test, a 60000 byte array is allocated
- * before the actual test code begins.
- */
-
- ................................................................
-
- START_TEST_TIMER;
-
- for(j=0; j < 5; j++)
- {
-
- /*
- * The array is initialized first. A non-random spreading setup
- * is used to insure the same values are used for every sorting
- * pass...this lessens the possibility of timing changes due to
- * order dependency of the routine.
- */
-
- for(i=0; i < 30000; i++) sarray[i] = (i % 2) ? (WORD)30000-i : (WORD)i;
-
- gap = 30000 / 2;
- do {
- do {
- nex = FALSE;
- for(i=0; i < 30000-gap; i++)
- {
- if(sarray[i] > sarray[i+gap])
- {
- temp = sarray[i];
- sarray[i] = sarray[i+gap];
- sarray[i+gap] = temp;
- nex = TRUE;
- }
- }
- } while(nex);
- gap /= 2;
- } while(gap);
- }
-
- STOP_TEST_TIMER;
-
- /* Clean up code and result calculation should follow at this point. */
-
- ...................................................................
- }
-
- ==============================================================================
-
- TGTest
-
- Text and Graphics Test. This is a test of the text throughput on the
- system in question. Since OS calls are used again, this will have an advantage
- on systems with the OS kernel in a fast memory medium, and will also have
- advantage on those systems with more efficiency CHIP RAM access. There are
- also some position variables which are calculated during the test, so this
- does not simply show the speed of the various text routines used, but also
- the overall efficiency of system when executing the routine's entire job.
- A decision step is also involved in drawing mode selection, thus contributing
- to the overall view of the text output and calculation efficiency of the
- system. This test also tends to reflect the efficiency of the system
- whe utilizing various windowing routines.
-
- void TGTest()
- {
- struct Screen *TTScrn;
- struct Window *TTWin;
- struct RastPort *TTRp;
- UWORD opens;
- UWORD xpos;
- UWORD ypos = 29;
- UWORD scrolls = 0;
- UWORD color = 0;
- UWORD drmd = JAM1;
-
- if(!(TTScrn = OpenScreen(&TTNewScrn))) return(FALSE);
- LoadRGB4(&(TTScrn->ViewPort),TGTstCols,16);
- ScreenToFront(TTScrn);
- TTNewWin.Screen = TTScrn;
-
- START_TEST_TIMER;
-
- for(opens = 0; opens < 7; opens++)
- {
- TTNewWin.Width -= (opens * 20);
- TTNewWin.Height -= (opens * 10);
- TTNewWin.LeftEdge = (opens * 20);
- TTNewWin.TopEdge = (opens * 10);
- if(!(TTWin = OpenWindow(&TTNewWin)))
- {
- STOP_TEST_TIMER;
- CloseScreen(TTScrn);
- return(FALSE);
- }
-
- TTRp = TTWin->RPort;
- SetDrMd(TTRp,drmd);
- SetAPen(TTRp,color);
-
- while(scrolls < 30)
- {
- xpos = 20;
- while(xpos < (TTWin->Width - (TextLength(TTRp,TestStr,strlen(TestStr)) + 9)))
- {
- switch(drmd)
- {
- case JAM1 :
- drmd = JAM2;
- break;
- case JAM2 :
- drmd = COMPLEMENT;
- break;
- case COMPLEMENT :
- drmd = INVERSVID;
- break;
- case INVERSVID :
- drmd = JAM1;
- break;
- }
- SetDrMd(TTRp,drmd);
- color = (color == 15) ? 0 : color + 1;
- SetAPen(TTRp,(color = (color == 15) ? 0 : color + 1));
- if(drmd != JAM1) SetBPen(TTRp,(color > 1) ? color-2 : color + 1);
-
- Move(TTRp,xpos,ypos);
- Text(TTRp,TestStr,strlen(TestStr));
-
- xpos += TextLength(TTRp,TestStr,strlen(TestStr));
- }
- ypos += 9;
- if(ypos > (TTWin->Height - 20))
- {
- ypos = (TTWin->Height - 20);
- ScrollRaster(TTRp,0,9,15,22,(TTWin->Width - 12),(TTWin->Height - 18));
- scrolls++;
- }
- }
- CloseWindow(TTWin);
- SetRast(&(TTScrn->RastPort),0);
- ypos = 29; scrolls = 0; color = 0;
- }
-
- STOP_TEST_TIMER;
-
- /* Clean up routines should follow at this point */
-
- ..................................................................
- }
-
- ==============================================================================
-
- FMath
-
- The FMath test is very similar to the IMath test with the exception that
- floating point math is the primary interest as opposed to integer operations.
- Single-precision operations are utilized for this test. The rough code
- outline is given below:
-
-
- void FMath()
- {
- float a;
- float b;
- float c;
- UWORD i;
-
- a = 45.43;
- b = 2.22;
- c = 2.0;
-
- START_TEST_TIMER;
-
- for(i=0; i < 20000 ; i++)
- {
- a = (a * b) + (float)i;
- c += ((a * b) / (float)i) + 1.0;
- c -= (c / a) - (float)i;
- c += ((c / a) * (float)i) + 1.0;
- a = (a * b) + (float)i;
- c -= (c / a) - (float)i;
- c += ((a * b) / (float)i) + 1.0;
- c -= ((c / a) * (float)i) + 1.0;
- a = (a * b) + (float)i;
- c += (c / a) - (float)i;
- c -= ((a * b) / (float)i) + 1.0;
- c += ((c / a) * (float)i) + 1.0;
- a = (a * b) + (float)i;
- c -= (c / a) - (float)i;
- }
-
- STOP_TEST_TIMER;
-
- /*
- * Again, at this point a global 'dummy' variable is used to assure that
- * code above is not optimized out. This makes a global optimizer
- * believe the above results are needed in order to assign the
- * dummy variable a value
- */
-
- TestFltDummy = a+b+c;
-
- ....................................................................
- }
-
- ==============================================================================
-
- FMatrix
-
- The FMatrix test is almost completely identical to the standard integer
- matrix test, with the exception that the data being manipulated is double
- precision floating point numbers. The code outline is given below:
-
-
- void FMatrix()
- {
- double *MatrixA;
- double *MatrixB;
- double *MatrixC;
- UWORD i;
- UWORD j;
- UWORD k;
-
- /*
- * Not shown: The 3 matrices must be allocated ( 12800 bytes each )
- * for the following test. Next, shown below, matrices A and B are
- * initialized with data.
- */
-
- for(i=0; i < 40; i++)
- {
- for(j=0; j < 40; j++)
- {
- MatrixA[40*i+j] = (double)(i+j);
- MatrixB[40*i+j] = (double)(i+j) * (double)(j-i);
- }
- }
-
- /*
- * The actual test code begins below.
- */
-
- START_TEST_TIMER;
-
- for(k=0; k < 50; k++)
- {
- fmatrix_mult(MatrixA,MatrixB,MatrixC,40,40);
- for(i=0; i < 40; i++)
- {
- fmatrix_row_swap(MatrixC,i,39-i,40);
- fmatrix_col_swap(MatrixC,39-i,i,40);
- }
- fmatrix_add(MatrixC,MatrixA,MatrixB,40,40);
- fmatrix_sub(MatrixB,MatrixA,MatrixC,40,40);
- fmatrix_transpose(MatrixC,MatrixA,40,40);
- }
-
- STOP_TEST_TIMER;
-
- /*
- * Again, clean-up and memory deallocation is performed here, though
- * not shown.
- */
-
- ..................................................................
- }
-
- /*
- * This function swaps rows in a double FP matrix.
- */
-
- void fmatrix_row_swap(double *mat, UWORD ra, UWORD rb, UWORD ncols)
- {
- UWORD c;
- double t;
-
- for(c=0; c < ncols; c++)
- {
- t = mat[ra*ncols+c];
- mat[ra*ncols+c] = mat[rb*ncols+c];
- mat[rb*ncols+c] = t;
- }
- }
-
- void fmatrix_col_swap(double *mat, UWORD ca, UWORD cb, UWORD nrows)
- {
- UWORD r;
- double t;
-
- for(r=0; r < nrows; r++)
- {
- t = mat[r*nrows+ca];
- mat[r*nrows+ca] = mat[r*nrows+cb];
- mat[r*nrows+cb] = t;
- }
- }
-
- /*
- * Add the contents of two FP matrices, and store the result in a third.
- * Equivalent to [C] = [A] + [B]
- */
-
- void fmatrix_add(double *matA, double *matB, double *matC, UWORD rows, UWORD cols)
- {
- UWORD r;
- UWORD c;
-
- for(r=0; r < rows; r++)
- {
- for(c=0; c < cols; c++)
- {
- matC[r*cols+c] = matA[r*cols+c] + matB[r*cols+c];
- }
- }
- }
-
- /*
- * Subtract the contents of two FP matrices, and store the result in a third.
- * Equivalent to [C] = [A] - [B].
- */
-
- void fmatrix_sub(double *matA, double *matB, double *matC, UWORD rows, UWORD cols)
- {
- UWORD r;
- UWORD c;
-
- for(r=0; r < rows; r++)
- {
- for(c=0; c < cols; c++)
- {
- matC[r*cols+c] = matA[r*cols+c] - matB[r*cols+c];
- }
- }
- }
-
- /*
- * Subtract the contents of two FP matrices, and store the result in a third.
- * Equivalent to [C] = [A] * [B].
- */
-
- void fmatrix_mult(double *matA, double *matB, double *matC, UWORD rows, UWORD cols)
- {
- UWORD r;
- UWORD c;
-
- for(r=0; r < rows; r++)
- {
- for(c=0; c < cols; c++)
- {
- matC[r*cols+c] = matA[r*cols+c] * matB[r*cols+c];
- }
- }
- }
-
- /*
- * Transpose the contents of FP matrix [B] to FP matrix [A]
- */
-
- void fmatrix_transpose(double *matA, double *matB, UWORD rows, UWORD cols)
- {
- UWORD r;
- UWORD c;
- double t;
-
- for(r=0; r < rows; r++)
- {
- for(c=0; c < cols; c++)
- {
- t = matA[r*cols+c];
- matA[r*cols+c] = matB[r*cols+c];
- matB[r*cols+c] = t;
- }
- }
- }
-
-
- ==============================================================================
-
- Savage
-
- The Savage benchmark is a test almost exclusively consisting of floating-
- point transcendental functions. It is a fairly well known test, used a fair
- amount for basic trancendental function evaluation. It is very simple in
- nature, as can be seen below:
-
- void Savage()
- {
- UWORD i;
- double a = 1.0L;
-
- START_TEST_TIMER;
-
- for(i=0; i < 40000; i++)
- {
- a = tan(atan(exp(log(sqrt(a*a))))) + 1.0L;
- }
-
- STOP_TEST_TIMER;
-
- /*
- * And that's the basic essence to the test...
- */
-
- ...........................................................
- }
-
- ===========================================================================
- Whetstone
-
- The Whetstone test is a fairly popular, albeit older, test of system
- performance. Because it deals with floating point as well as other
- areas, it is placed in the floating point test category. The test has
- been slightly modified in that the accuracy tests it does (checks) have
- been replaced...a function call is still used to maintain the integrity of
- the test, but accuracy is not a testing concern in this setup.
-
- void Whetstone_Test()
- {
- BOOL tempbool;
-
- START_TEST_TIMER;
-
- n1_O = 2L * wt_O;
- n2_O = 10L * wt_O;
- n3_O = 14L * wt_O;
- n4_O = 345L * wt_O;
- n5_O = 0L;
- n6_O = 95L * wt_O;
- n7_O = 32L * wt_O;
- n8_O = 800L * wt_O;
- n9_O = 616L * wt_O;
- n10_O = 0L;
- n11_O = 93L * wt_O;
-
- /***********************************/
- /* MODULE 1: Simple Identifiers */
- /***********************************/
-
- xx_O_d.one = 1.0;
- xx_O_d.two = -1.0;
- xx_O_d.three = -1.0;
- xx_O_d.four = -1.0;
-
- for(i_O = 0L; i_O < n1_O; i_O++)
- {
- xx_O_d.one = ( xx_O_d.one + xx_O_d.two + xx_O_d.three - xx_O_d.four ) * T;
- xx_O_d.two = ( xx_O_d.one + xx_O_d.two - xx_O_d.three + xx_O_d.four ) * T;
- xx_O_d.three = ( xx_O_d.one - xx_O_d.two + xx_O_d.three + xx_O_d.four ) * T;
- xx_O_d.four = (-xx_O_d.one + xx_O_d.two + xx_O_d.three + xx_O_d.four ) * T;
- }
-
- norm_O_d = sqrt(sqr(xx_O_d.one)+sqr(xx_O_d.two)+sqr(xx_O_d.three)+sqr(xx_O_d.four));
- tempbool = ((fabs(norm_O_d - exp(0.35735-n1_O*6.1e-5))/norm_O_d) <= 0.1);
- Check(1,tempbool);
-
- /*******************************/
- /* MODULE 2: Array Elements */
- /*******************************/
-
- e1_O_d[0] = 1.0;
- e1_O_d[1] = -1.0;
- e1_O_d[2] = -1.0;
- e1_O_d[3] = -1.0;
-
- for(i_O=0L; i_O < n2_O; i_O++)
- {
- e1_O_d[0] = ( e1_O_d[0] + e1_O_d[1] + e1_O_d[2] - e1_O_d[3] ) * T;
- e1_O_d[1] = ( e1_O_d[0] + e1_O_d[1] - e1_O_d[2] + e1_O_d[3] ) * T;
- e1_O_d[2] = ( e1_O_d[0] - e1_O_d[1] + e1_O_d[2] + e1_O_d[3] ) * T;
- e1_O_d[3] = (-e1_O_d[0] + e1_O_d[1] + e1_O_d[2] + e1_O_d[3] ) * T;
- }
-
- norm_O_d = sqrt(sqr(e1_O_d[0])+sqr(e1_O_d[1])+sqr(e1_O_d[2])+sqr(e1_O_d[3]));
- tempbool = ((fabs(norm_O_d - exp(0.35735-n2_O*6.1e-5))/norm_O_d) <= 0.1);
- Check(2,tempbool);
-
- /*************************************/
- /* MODULE 3: Array as a Parameter */
- /*************************************/
-
- t3_O_d = 1.0 / T;
-
- for(i_O = 0; i_O < n3_O; i_O++) pa(e1_O_d);
-
- norm_O_d = sqrt(sqr(e1_O_d[0])+sqr(e1_O_d[1])+sqr(e1_O_d[2])+sqr(e1_O_d[3]));
- tempbool = ((fabs(norm_O_d - exp(0.35735-(n3_O*6+n2_O)*6.1e-5))/norm_O_d) <= 0.1);
- Check(3,tempbool);
-
- /**********************************/
- /* MODULE 4: Conditional Jumps */
- /**********************************/
-
- jj_O = 1L;
-
- for(i_O = 0; i_O < n4_O; i_O++)
- {
- if(jj_O == 1L)
- jj_O = 2L;
- else
- jj_O = 3L;
- if(jj_O > 2L)
- jj_O = 0L;
- else
- jj_O = 1L;
- if(jj_O < 1L)
- jj_O = 1L;
- else
- jj_O = 0L;
- }
- tempbool = (jj_O == (!(wt_O & 1L)));
- Check(4,tempbool);
-
- /***********************************/
- /* MODULE 6: Integer Arithmetic */
- /***********************************/
-
- ij_O = 1;
- ik_O = 2;
- il_O = 3;
-
- for(i_O=0 ; i_O < n6_O; i_O++)
- {
- ij_O = ij_O * (ik_O - ij_O) * (il_O - ik_O);
- ik_O = il_O * ik_O - (il_O - ij_O) * ik_O;
- il_O = (il_O - ik_O) * (ik_O + ij_O);
-
- e1_O_d[il_O-2] = ij_O + ik_O + il_O;
- e1_O_d[ik_O-2] = ij_O * ik_O * il_O;
- }
-
- tempbool = ((ij_O==1L) && (ik_O==2L) && (il_O==3L));
- Check(6,tempbool);
-
- /****************************************/
- /* MODULE 7: Trigonometric Functions */
- /****************************************/
-
- x_O_d = 0.5;
- y_O_d = 0.5;
-
- for(i_O=0L; i_O < n7_O; i_O++)
- {
- x_O_d = T * atan(T2 * sin(x_O_d) * cos(x_O_d) / (cos(x_O_d+y_O_d) + cos(x_O_d-y_O_d) - 1.0));
- y_O_d = T * atan(T2 * sin(y_O_d) * cos(y_O_d) / (cos(x_O_d+y_O_d) + cos(x_O_d-y_O_d) - 1.0));
- }
-
- tempbool = (((T - wt_O * 0.0015) <= x_O_d) && (x_O_d <= (T - wt_O * 0.0004)) &&
- ((T - wt_O * 0.0015) <= y_O_d) && (y_O_d <= (T - wt_O * 0.0004)));
- Check(7,tempbool);
-
- /********************************/
- /* MODULE 8: Procedure Calls */
- /********************************/
-
- x_O_d = 1.0;
- y_O_d = 1.0;
- z_O_d = 1.0;
-
- for(i_O = 1L; i_O <= n8_O; i_O++) p3((double)(y_O_d*(double)i_O),(double)(y_O_d+z_O_d),&z_O_d);
- tempbool = ((fabs(z_O_d - (0.99983352*n8_O - 0.999555651))) <= (n8_O*1.0e-6));
- Check(8,tempbool);
-
- /*********************************/
- /* MODULE 9: Array References */
- /*********************************/
-
- ij_O = 0;
- ik_O = 1;
- il_O = 2;
-
- e1_O_d[0] = 1.0;
- e1_O_d[1] = 2.0;
- e1_O_d[2] = 3.0;
-
- for(i_O=0L; i_O < n9_O; i_O++) p0();
-
- tempbool = ((e1_O_d[0] == 3.0) && (e1_O_d[1] == 2.0) && (e1_O_d[2] == 3.0));
- Check(9,tempbool);
-
- /***********************************/
- /* MODULE 10: Integer Arithmetic */
- /***********************************/
-
- jj_O = 2L;
- kk_O = 3L;
-
- for(i_O=0;i_O<n10_O;i_O++)
- {
- jj_O = jj_O + kk_O;
- kk_O = jj_O + kk_O;
- jj_O = kk_O - jj_O;
- kk_O = kk_O - jj_O - jj_O;
- }
- tempbool = ((jj_O==2) && (kk_O==3));
- Check(10,tempbool);
-
- /***********************************/
- /* MODULE 11: Standard Functions */
- /***********************************/
-
- x_O_d = 0.75;
-
- for(i_O = 0L; i_O < n11_O; i_O++) x_O_d = sqrt(exp(log(x_O_d) / T1));
-
- estimate_O_d = 1.0L - exp(-0.0447L*wt_O + log(0.26L));
- tempbool = ((fabs(estimate_O_d-x_O_d)/estimate_O_d <= (0.0006 + 0.065/(5.0+(double)wt_O))));
- Check(11,tempbool);
-
- /**************************************/
-
- STOP_TEST_TIMER;
-
- /*
- * Cleanup and result calculations are omitted here, as the main
- * portion of the actual test is the concern.
- */
-
- }
-
- static double sqr(register double x)
- {
- x *= x;
- return(x);
- }
-
- static void pa(register double *e)
- {
- register WORD j = 0;
-
- do {
- e[0] = ( e[0] + e[1] + e[2] - e[3] ) * T;
- e[1] = ( e[0] + e[1] - e[2] + e[3] ) * T;
- e[2] = ( e[0] - e[1] + e[2] + e[3] ) * T;
- e[3] = (-e[0] + e[1] + e[2] + e[3] ) / t3_O_d;
- j++;
- } while(j < 6);
- }
-
-
- static void p0()
- {
- e1_O_d[ij_O] = e1_O_d[ik_O];
- e1_O_d[ik_O] = e1_O_d[il_O];
- e1_O_d[il_O] = e1_O_d[ij_O];
- }
-
- static void p3(register double x, register double y, register double *z)
- {
- x = T * (*z + x);
- y = T * (x + y);
- *z = (x + y) / T2;
- }
-
- static BOOL Check(register UWORD ModuleNo, register BOOL Condition)
- {
- return((Condition) ? TRUE : FALSE);
- }
-
- ===========================================================================
- FTrace
-
- The FTrace test is in actuality a portion of a ray-tracing algorithm
- set in use as a benchmark. Its construction is fairly simple, and the
- main outline is given below:
-
- BOOL FTrace_CP_N()
- {
- WORD iter;
- double od_fline;
- double od_cline;
- ULONG nulltime;
-
- /*
- * Initialization not shown to focus on the main test itself
- */
-
- START_TEST_TIMER;
-
- for(iter=0; iter < LOOPCOUNT; iter++)
- {
- for(paraxial=0; paraxial <= 1; paraxial++)
- {
- trace_line(4,clear_aperture / 2.0L);
- od_sa[paraxial][0] = object_distance;
- od_sa[paraxial][1] = axis_slope_angle;
- }
- paraxial = 0;
- trace_line(3,clear_aperture / 2.0L);
- od_cline = object_distance;
- trace_line(6,clear_aperture / 2.0L);
- od_fline = object_distance;
- aberr_lspher = od_sa[1][0] - od_sa[0][0];
- aberr_osc = 1.0L - (od_sa[1][0] * od_sa[1][1]) /
- (sin(od_sa[0][1]) * od_sa[0][0]);
- aberr_lchrom = od_fline - od_cline;
- max_lspher = sin(od_sa[0][1]);
- max_lspher = 0.0000926L / (max_lspher * max_lspher);
- max_osc = 0.0025L;
- max_lchrom = max_lspher;
- }
-
- STOP_TEST_TIMER;
-
- ..............................................................
- }
-
- /*-----------------------------------------------------------------------------*/
-
- void trace_line(register WORD line, register double ray_h)
- {
- register WORD i;
-
- object_distance = 0.0L;
- ray_height = ray_h;
- from_index = 1.0L;
-
- for(i = 1; i <= current_surfaces; i++)
- {
- radius_of_curvature = s[i][1];
- to_index = s[i][2];
- if(to_index > 1.0L)
- to_index = to_index + ((spectral_line[4] - spectral_line[line]) /
- (spectral_line[3] - spectral_line[6])) *
- ((s[i][2] - 1.0L) / s[i][3]);
- transit_surface();
- from_index = to_index;
- if(i < current_surfaces) object_distance = object_distance - s[i][4];
- }
- }
-
- /*----------------------------------------------------------------------------*/
-
- void transit_surface()
- {
- register double iang; /* Incidence angle */
- register double rang;
- register double iang_sin;
- register double rang_sin;
- double old_axis_slope_angle;
- double sagitta;
-
- if(paraxial)
- {
- if(radius_of_curvature != 0.0L)
- {
- if(object_distance == 0.0L)
- {
- axis_slope_angle = 0.0L;
- iang_sin = ray_height / radius_of_curvature;
- }
- else
- iang_sin = ((object_distance - radius_of_curvature) /
- radius_of_curvature) * axis_slope_angle;
-
- rang_sin = (from_index / to_index) * iang_sin;
- old_axis_slope_angle = axis_slope_angle;
- axis_slope_angle = axis_slope_angle + iang_sin - rang_sin;
- if(object_distance != 0.0L)
- ray_height = object_distance * old_axis_slope_angle;
- object_distance = ray_height / axis_slope_angle;
- return;
- }
- object_distance = object_distance * (to_index / from_index);
- axis_slope_angle = axis_slope_angle * (from_index / to_index);
- return;
- }
-
- if(radius_of_curvature != 0.0L)
- {
- if(object_distance == 0.0L)
- {
- axis_slope_angle = 0.0L;
- iang_sin = ray_height / radius_of_curvature;
- }
- else
- {
- iang_sin = ((object_distance - radius_of_curvature) /
- radius_of_curvature) * sin(axis_slope_angle);
- }
- iang = asin(iang_sin);
- rang_sin = (from_index / to_index) * iang_sin;
- old_axis_slope_angle = axis_slope_angle;
- axis_slope_angle = axis_slope_angle + iang - asin(rang_sin);
- sagitta = sin((old_axis_slope_angle + iang) / 2.0L);
- sagitta = 2.0L * radius_of_curvature*sagitta*sagitta;
- object_distance = ((radius_of_curvature *
- sin(old_axis_slope_angle + iang)) *
- cot(axis_slope_angle)) + sagitta;
- return;
- }
-
- rang = -asin((from_index / to_index) * sin(axis_slope_angle));
- object_distance = object_distance * ((to_index * cos(-rang)) /
- (from_index * cos(axis_slope_angle)));
- axis_slope_angle = -rang;
- }
-
- ===========================================================================
- CplxTest
-
- The CplxTest is a simple test of complex arithmetic methods. Complex
- arithmetic finds its use in many scientific and engineering fields and
- some basic arithmetic using this number form is applied for this test.
-
-
- typedef struct cplx {
- double r;
- double i;
- } complex;
-
- void CplxTest()
- {
- UWORD i;
- complex c1 = { 0.243223L,1.23412L };
- complex c2 = { -0.243222L,-1.23412L };
-
- START_TEST_TIMER;
-
- for(i=0; i < 3000; i++)
- {
- c1.r = creal(c1);
- c1.i = cimg(c1);
- c2.r = -(creal(c2));
- c2.i = -(cimg(c2));
-
- c1 = cadd(c1,c2);
- c2 = csub(c2,c1);
- c2 = cdiv(cmul(cinv(c1),cneg(c2)) ,c1);
- c1 = cexp(conj(c2));
- c1 = ccosh(csub(c1,c2));
- c2 = cmul(cdiv(c1,c2),cdiv(c2,c1));
- c2 = cexp(cadd(conj(c2),conj(c1)));
- }
-
- STOP_TEST_TIMER;
-
- .............................................................
-
- }
-
- complex cadd(complex o1, complex o2)
- {
- complex __aligned a1;
-
- a1.r = o1.r + o2.r;
- a1.i = o1.i + o2.i;
- return(a1);
- }
-
- complex csub(complex o1, complex o2)
- {
- complex __aligned a1;
-
- a1.r = o1.r - o2.r;
- a1.i = o1.i - o2.i;
- return(a1);
- }
-
- complex cmul(complex o1, complex o2)
- {
- complex __aligned a1;
-
- a1.r = (o1.r * o2.r) - (o1.i * o2.i);
- a1.i = (o1.r * o2.i) + (o1.i * o2.r);
- return(a1);
- }
-
- complex cinv(complex o1)
- {
- double __aligned mag;
- complex __aligned a1;
-
- mag = (o1.r * o1.r) + (o1.i * o1.i);
- a1.r = o1.r / mag;
- a1.i = o1.i / mag;
- return(a1);
- }
-
- complex cneg(complex o1)
- {
- complex __aligned a1;
-
- a1.r = -o1.r;
- a1.i = -o1.i;
- return(a1);
- }
-
- complex cdiv(complex o1, complex o2)
- {
- return(cmul(o1,cinv(o2)));
- }
-
- complex conj(complex o1)
- {
- complex __aligned a1;
-
- a1.r = o1.r;
- a1.i = -o1.i;
- return(a1);
- }
-
- complex cexp(complex o1)
- {
- double __aligned mag;
- complex __aligned a1;
-
- mag = exp(o1.r);
- a1.r = mag * cos(o1.i);
- a1.i = mag * sin(o1.i);
- return(a1);
- }
-
- complex ccosh(complex o1)
- {
- complex __aligned a1;
-
- a1 = cadd(cexp(o1),cexp(cneg(o1)));
- a1.r = 0.5 * a1.r;
- a1.i = 0.5 * a1.i;
- return(a1);
- }
-
- double creal(complex o1)
- {
- return(o1.r);
- }
-
- double cimg(complex o1)
- {
- return(o1.i);
- }
-